#include "stdafx.h"
#include <boost/test/auto_unit_test.hpp>
#include "bmock.hpp"
#include "bmock_control_tools_mock.hpp"
#include <vector>

namespace std
{
	ostream& operator << (ostream& os, const std::vector<int>& v) {
		for (size_t i = 0; i < v.size(); i++)
			os << v[i]; 
		return os;
	}

	istream& operator >> (istream& is, std::vector<int>& v) {
		for (size_t i = 0; i < v.size(); i++)
			is >> v[i]; 
		return is;
	}
}


struct test_fixture
{
	test_fixture() 
	{
		BMOCK_CREATE_MOCK(f1*);
		BMOCK_CREATE_MOCK(f2*);
		BMOCK_CREATE_MOCK(g*);
	}
};

template <typename T>
void f1(T v)
{
	MOCK_VOID(1, (IN(v)));
}

template <typename T, typename U>
T f2(T v1, U v2)
{
	MOCK(2, (IN(v1), IN(v2)));
	return v1;
}

template <typename T>
T g(int x, int y)
{
	MOCK(2, (IN(x), IN(y)));
	return T();
}

BMOCK_TEST(test_fixture, test_function_template_one_parameter)
{
	int x = 0;
	
	BMOCK_EXPECT(f1(x));
	BMOCK_REPLAY;
	f1(x);
	BMOCK_VERIFY;
}

BMOCK_TEST(test_fixture, test_function_template_two_parameters)
{
	int x = 1;
	double y = 1.1;

	BMOCK_EXPECT_RETURN(x, f2(x,y));
	BMOCK_EXPECT_RETURN(y, f2(y,x));
	BMOCK_REPLAY;
	BOOST_CHECK_EQUAL(x, f2(x,y));
	BOOST_CHECK_EQUAL(y, f2(y,x));
	BMOCK_VERIFY;
}

BMOCK_TEST(test_fixture, test_function_template_one_parameter_template)
{
	std::vector<int> vec;
	vec.push_back(5);
	vec.push_back(6);

	BMOCK_EXPECT(f1(vec));
	BMOCK_REPLAY;
	f1(vec);
	BMOCK_VERIFY;
}

BMOCK_TEST(test_fixture, test_function_template_two_parameters_template)
{
	std::vector<int> vec1;
	vec1.push_back(5);
	vec1.push_back(6);
	std::vector<int> vec2;
	vec1.push_back(7);
	vec1.push_back(8);


	BMOCK_EXPECT_RETURN(vec1, f2(vec1,vec2));
	BMOCK_EXPECT_RETURN(vec2, f2(vec2,vec1));
	BMOCK_REPLAY;
	BOOST_CHECK_EQUAL(vec1, f2(vec1,vec2));
	BOOST_CHECK_EQUAL(vec2, f2(vec2,vec1));
	BMOCK_VERIFY;
}

BMOCK_TEST(test_fixture, test_function_template_only_return_value_template)
{
	BMOCK_EXPECT_RETURN(3, g<int>(4,5));
	BMOCK_EXPECT_RETURN(3.3, g<double>(4,5));
	BMOCK_REPLAY;
	BOOST_CHECK_EQUAL(3, g<int>(4,5));
	BOOST_CHECK_EQUAL(3.3, g<double>(4,5));
	BMOCK_VERIFY;
}

BMOCK_TEST(test_fixture, test_function_template_only_return_value_template_template)
{
	std::vector<int> vec1,vec2;
	vec1.push_back(5);
	vec1.push_back(6);

	BMOCK_EXPECT_RETURN(vec1, g<std::vector<int> >(4,5));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(vec2 =  g<std::vector<int> >(4,5));
	BOOST_CHECK(vec1 == vec2);
	BMOCK_VERIFY;
}

